home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / jfetch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  21.4 KB  |  796 lines

  1. /* 
  2.  * jfetch.c --
  3.  *
  4.  *    Perform indexing on Jaquith archive system.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/jfetch.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "jaquith.h"
  21. #include "option.h"
  22.  
  23. static int    GetFileQuery   _ARGS_ ((int, QuerySpec *));
  24. static char **GetRegExpr     _ARGS_ ((int, int *));
  25. static int    ReturnFileData _ARGS_ ((int sock,
  26.                       T_FileStat *statInfoPtr,
  27.                       int tBufStream));
  28. static int    RecallTBuf     _ARGS_ ((char *archPath, int *tBufStreamPtr,
  29.                       T_FileStat *statInfoPtr,
  30.                       ArchConfig *archConfigPtr,
  31.                       int *inStreamPtr));
  32. static int    ReceiveIndxProc _ARGS_ ((T_FileStat *statInfoPtr,
  33.                        ReceiveBlk *receiveBlkPtr));
  34. static int   VerifyClient      _ARGS_ ((char *archPath, int sock,
  35.                     Caller *callerPtr));
  36.  
  37.  
  38. static char printBuf[T_MAXSTRINGLEN];
  39. static char *logPath;         /* pathname of log file */
  40. static FILE *memDbg = NULL;   /* stream for memory tracing */
  41.  
  42. int jDebug;                   /* Internal debugging only */
  43. int syserr = 0;               /* Our personal record of errno */
  44.  
  45. #define DEF_SOCK -1
  46. #define DEF_FLAGS -1
  47. #define DEF_DEBUG 0
  48. #define DEF_DISKLOW 70
  49. #define DEF_DISKHIGH 80
  50. #define DEF_USER ""
  51. #define DEF_GROUP ""
  52. #define DEF_HOST ""
  53. #define DEF_CLEANER ""
  54.  
  55. #define DEF_FILE_CNT 3
  56.  
  57. #define ROOTSUFFIX "/_ROOT"
  58.  
  59. typedef struct ReceiveBlk {
  60.     int sock;
  61.     char *archPath;
  62.     ArchConfig *archConfigPtr;
  63. } ReceiveBlk;
  64.  
  65. typedef struct parmTag {
  66.     int sock;
  67.     char *arch;
  68.     int flags;
  69.     char *root;
  70.     int debug;
  71.     int diskLow;
  72.     int diskHigh;
  73.     char *userName;
  74.     char *groupName;
  75.     char *hostName;
  76.     char *cleaner;
  77.     int fsyncFreq;
  78. } Parms;
  79.  
  80. Parms parms = {
  81.     DEF_SOCK,
  82.     DEF_ARCH,
  83.     DEF_FLAGS,
  84.     DEF_ROOT,
  85.     DEF_DEBUG,
  86.     DEF_DISKLOW,
  87.     DEF_DISKHIGH,
  88.     DEF_USER,
  89.     DEF_GROUP,
  90.     DEF_HOST,
  91.     DEF_CLEANER,
  92.     DEF_FSYNCFREQ
  93. };
  94.  
  95. Option optionArray[] = {
  96.     {OPT_INT, "socket", (char *)&parms.sock, "socket #"},
  97.     {OPT_STRING, "archive", (char *)&parms.arch, "archive name"},
  98.     {OPT_INT, "flags", (char *)&parms.flags, "option flags"},
  99.     {OPT_STRING, "root", (char *)&parms.root, "root of index tree"},
  100.     {OPT_TRUE, "debug", (char *)&parms.debug, "enable debugging output"},
  101.     {OPT_INT, "disklow", (char *)&parms.diskLow, "Low limit for usable disk (%)"},
  102.     {OPT_INT, "diskhigh", (char *)&parms.diskHigh, "High limit for usable disk (%)"},
  103.     {OPT_STRING, "username", (char *)&parms.userName, "Name of requestor"},
  104.     {OPT_STRING, "groupname", (char *)&parms.groupName, "Group name of requestor"},
  105.     {OPT_STRING, "hostname", (char *)&parms.hostName, "Machine name of requestor"},
  106.     {OPT_STRING, "cleaner", (char *)&parms.cleaner, "cleaning program"},
  107.     {OPT_INT, "fsyncfreq", (char *)&parms.fsyncFreq, "Do fsync every N files. Ignored."}
  108. };
  109. int numOptions = sizeof(optionArray) / sizeof(Option);
  110.  
  111.  
  112. /*
  113.  *----------------------------------------------------------------------
  114.  *
  115.  * jfetch --
  116.  *
  117.  *    Main driver for indexing operations
  118.  *
  119.  * Results:
  120.  *    none.
  121.  *
  122.  * Side effects:
  123.  *    none.
  124.  *
  125.  * Note: jfetch is invoked from the Jaquith switchboard process,
  126.  *       not from the command line.
  127.  *
  128.  *----------------------------------------------------------------------
  129.  */
  130.  
  131. int
  132. main(argc, argv)
  133.     int argc;                 /* See Option Array */
  134.     char *argv[];
  135. {
  136.     int sock;
  137.     int i;
  138.     QuerySpec fileSpec;
  139.     int retCode;
  140.     FILE *indxStream;
  141.     Q_Handle *indxQueue;
  142.     T_FileStat *statInfoPtr;
  143.     int regExpCnt;
  144.     char **regList;
  145.     char *indxPath;
  146.     char *archPath;
  147.     int indxCnt;
  148.     ReceiveBlk receiveBlk;
  149.     char null = '\0';
  150.     char perm;
  151.     int ignoreTopLevelDir;
  152.     ArchConfig archConfig;
  153.     static char star[] = "*";
  154.     static T_FileStat dummyFile =
  155.     {"", "", "", "", "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  156.     Caller caller;
  157.  
  158. /*    memDbg = fopen("jfetch.mem","w"); */
  159.     MEM_CONTROL(8192, memDbg, TRACEMEM+TRACECALLS, 4096);
  160.  
  161.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  162.  
  163.     sock = parms.sock;
  164.     jDebug = parms.debug;
  165.  
  166.     archPath = Str_Cat(3, parms.root, "/", parms.arch);
  167.     logPath = Str_Cat(3, archPath, "/", ARCHLOGFILE);
  168.  
  169.     sprintf(printBuf,"Caller %s@%s, flags 0x%x\n",
  170.         parms.userName, parms.hostName, parms.flags);
  171.     Log_AtomicEvent("jfetch", printBuf, logPath);
  172.  
  173.     /* Authorize user to send data, or not, as the case may be */
  174.     if (VerifyClient(archPath, sock, &caller) != T_SUCCESS) {
  175.     exit(0);
  176.     }
  177.  
  178.     if (Admin_ReadArchConfig(archPath, &archConfig) != T_SUCCESS) {
  179.     sprintf(printBuf,"Admin_ReadArchConfig failed: errno %d\n", syserr);
  180.     Log_AtomicEvent("jfetch", printBuf, logPath);
  181.     Sock_SendRespHdr(sock, T_ADMFAILED, syserr);
  182.     return -1;
  183.     }
  184.  
  185.     if ((retCode=GetFileQuery(sock, &fileSpec)) != T_SUCCESS) {
  186.     if (jDebug) {
  187.         fprintf(stderr,"didn't get query\n");
  188.     }
  189.     Sock_SendRespHdr(sock, retCode, 0);
  190.     return -1;
  191.     }
  192.  
  193.     Sock_SendRespHdr(sock, T_SUCCESS, 0);
  194.     regList = GetRegExpr(sock, ®ExpCnt);
  195.  
  196.     if ((retCode != T_SUCCESS) || (regList == NULL)) {
  197.     Log_AtomicEvent("jfetch", "Couldn't get request\n", logPath);
  198.     Sock_SendRespHdr(sock, T_BADMSGFMT, syserr);
  199.     exit(T_BADMSGFMT);
  200.     }
  201.  
  202.     receiveBlk.archPath = archPath;
  203.     receiveBlk.sock = sock;
  204.     receiveBlk.archConfigPtr = &archConfig;
  205.  
  206.     indxQueue = Q_Create("indx", 0);
  207.  
  208.     for (i=0; (i<regExpCnt) && (retCode == T_SUCCESS); i++) {
  209.     sprintf(printBuf,"Request: %s\n", regList[i]);
  210.     Log_AtomicEvent("jfetch", printBuf, logPath);
  211.  
  212.     if ((fileSpec.fileName=STRRCHR(regList[i], '/')) != NULL) {
  213.         fileSpec.fileName++;
  214.     } else {
  215.         fprintf(stderr,"No last slash\n");
  216.         retCode = T_BADMSGFMT;
  217.         break;
  218.     }
  219.     if ((retCode=Indx_MakeIndxList(archPath, regList[i], indxQueue))
  220.         != T_SUCCESS) {
  221.         fprintf(stderr,"Bad retcode from Indx_MakeIndxList\n");
  222.         break;
  223.     }
  224.     indxCnt = Q_Count(indxQueue);
  225.     if (jDebug) {
  226.         fprintf(stderr,"indxQueue has %d entries. rc %d\n",
  227.             indxCnt, retCode);
  228.     }
  229.     if ((parms.flags & T_NODATA) && (fileSpec.recurse > 0)) {
  230.         ignoreTopLevelDir = 1;
  231.     } else {
  232.         ignoreTopLevelDir = 0;
  233.     }
  234.     while ((indxCnt-- > 0) && (retCode == T_SUCCESS)) {
  235.         indxPath = (char *)Q_Remove(indxQueue);
  236.         if ((retCode=Indx_Match(&fileSpec, indxPath, archPath, &caller,
  237.                     ReceiveIndxProc, &receiveBlk,
  238.                     ignoreTopLevelDir)) != T_SUCCESS) {
  239.         fprintf(stderr,"Bad retcode from Indx_match\n");
  240.         }
  241.         MEM_FREE("jfetch", indxPath);
  242.     }
  243.     MEM_FREE("jfetch",regList[i]);
  244.     MEM_REPORT("jfetch", ALLROUTINES, SORTBYOWNER);
  245.     }
  246.     
  247.     Sock_WriteFileStat(sock, &dummyFile, 0);
  248.  
  249.     sprintf(printBuf,"Done. retCode %d, errno %d\n", retCode, syserr);
  250.     Log_AtomicEvent("jfetch", printBuf, logPath);
  251.  
  252.     Sock_SendRespHdr(sock, retCode, syserr);
  253.  
  254.     if (fileSpec.compAbstract) {
  255.     MEM_FREE("jfetch",
  256.          (char *)fileSpec.compAbstract);/* allocated by regcomp */
  257.     }
  258.  
  259.     Q_Destroy(indxQueue);
  260.     MEM_FREE("jfetch", (char *)regList);
  261.     MEM_FREE("jfetch", archPath);
  262.  
  263.     MEM_REPORT("jfetch", ALLROUTINES, SORTBYOWNER);
  264.  
  265.     return retCode;
  266.  
  267. }
  268.  
  269.  
  270. /*
  271.  *----------------------------------------------------------------------
  272.  *
  273.  * RecallTBuf --
  274.  *
  275.  *    Recall a tbuf from tape if necessary and open it
  276.  *
  277.  * Results:
  278.  *      return code
  279.  *
  280.  * Side effects:
  281.  *    Opens tbuf.
  282.  *
  283.  *----------------------------------------------------------------------
  284.  */
  285.  
  286. static int
  287. RecallTBuf(archPath, tBufStreamPtr, statInfoPtr, archConfigPtr, inStreamPtr)
  288.     char *archPath;           /* full path to archive */
  289.     int *tBufStreamPtr;       /* receiving stream (updated) */
  290.     T_FileStat *statInfoPtr;  /* file specification (updated) */
  291.     ArchConfig *archConfigPtr; /* archive configuration params */
  292.     int *inStreamPtr;         /* active volume descriptor */
  293. {
  294.     int retCode;
  295.     int size;
  296.     int tBufId = statInfoPtr->tBufId;
  297.     int volId = statInfoPtr->volId;
  298.     int filemark = statInfoPtr->filemark+1;
  299.     int status;
  300.     char buf[T_TARSIZE];
  301.     int len;
  302.     int pid;
  303.     int percentUsed;
  304.     long blocksFree;
  305.     char lowChar[20];
  306.     char highChar[20];
  307.     int sleepSecs = 5;
  308.     int retryCnt = 0;
  309.     static char devName[T_MAXPATHLEN];
  310.     static char *devNamePtr = devName;
  311.     static int curVolId = -1;
  312.     static int curFilemark = 0;
  313.     static int sock;
  314.     VolStatus volStatus;
  315.     char recallPath[T_MAXPATHLEN];
  316.  
  317.     /* see if the buffer's already here */
  318.     if (TBuf_Open(archPath, tBufId, tBufStreamPtr, NULL, O_RDONLY)
  319.     != T_SUCCESS) {
  320.     return T_BUFFAILED;
  321.     } else if (*tBufStreamPtr != -1) {
  322.     if (jDebug) {
  323.         fprintf(stderr,"Using tbuf.%d\n", tBufId);
  324.     }
  325.     return T_SUCCESS;
  326.     }
  327.  
  328.     sprintf(printBuf,"Recalling tbuf.%d from volume %d, location %d\n",
  329.         tBufId, volId, filemark);
  330.     Log_AtomicEvent("jfetch", printBuf, logPath);
  331.     if (jDebug) {
  332.     fprintf(stderr,"(%d) %s", Time_Stamp(), printBuf);
  333.     }
  334.  
  335.     Admin_GetDiskUse(parms.root, &percentUsed, &blocksFree);
  336.  
  337.     /* Let cleaner make some space */
  338.     if ((percentUsed > parms.diskHigh) &&
  339.     (Admin_AvailVolInfo(archPath))) {
  340.     fprintf(stderr,"fetch: Below threshold or availvolinfo failed\n");
  341.     if ((pid=fork()) == -1) {
  342.         sprintf(printBuf, "Fork of cleaner failed: %d\n", errno);
  343.         Log_AtomicEvent("jfetch", printBuf, logPath);
  344.     } else if (pid == 0) {
  345.         sprintf(lowChar, "%d", parms.diskLow);
  346.         sprintf(highChar, "%d", parms.diskHigh);
  347.         execlp(parms.cleaner, parms.cleaner,
  348.            "-root", parms.root,
  349.            "-arch", "*.arch",
  350.            "-tbufid", "-1",
  351.            "-username", parms.userName,
  352.            "-hostname", parms.hostName,
  353.            "-debug", (jDebug) ? "1" : "0",
  354.            "-newvol", "0",
  355.            "-disklow", lowChar,
  356.            "-diskhigh", highChar,
  357.            NULL);
  358.         sprintf(printBuf,"Execlp of cleaner failed: %d\n", errno);
  359.         Log_AtomicEvent("jfetch", printBuf, logPath);
  360.         _exit(T_EXECFAILED);
  361.     }
  362.     }
  363.  
  364.     /* Need to acquire the volume? */
  365.     if (curVolId != volId) {
  366.     if (curVolId != -1) {
  367.         if (jDebug) {
  368.         fprintf(stderr, "recallTBuf: releasing vol %d\n", curVolId);
  369.         }
  370.         retCode = Sock_WriteString(sock, parms.userName, 0);
  371.         retCode += Sock_WriteInteger(sock, S_CMDFREE);
  372.         retCode += Sock_WriteInteger(sock, curVolId);
  373.     }
  374.     if (jDebug) {
  375.         fprintf(stderr, "(%d) RecallTBuf: acquiring vol %d\n",
  376.             Time_Stamp(), volId);
  377.     }
  378.  
  379.     if ((sock=Sock_SetupSocket(archConfigPtr->mgrPort,
  380.                    archConfigPtr->mgrServer, 0)) == -1) {
  381.         sprintf(printBuf,"Jfetch couldn't connect to jmgr at %s port %d. errno %d\n",
  382.             archConfigPtr->mgrServer, archConfigPtr->mgrPort, syserr);
  383.         Log_AtomicEvent("jfetch", printBuf, logPath);
  384.         if (Utils_SendMail(ARCHMASTER, printBuf, "alert") != 0) {
  385.         sprintf(printBuf, "Got return code %d mailing alert to %s\n",
  386.             retCode, ARCHMASTER);
  387.         Log_AtomicEvent("Jfetch", printBuf, logPath);
  388.         }
  389.         return T_FAILURE;
  390.     }
  391.     
  392.     retCode = Sock_WriteString(sock, parms.userName, 0);
  393.     retCode += Sock_WriteInteger(sock, S_CMDLOCK);
  394.     retCode += Sock_WriteInteger(sock, volId);
  395.     retCode += Sock_ReadInteger(sock, &status);    
  396.  
  397.     if ((retCode != T_SUCCESS) || (status != T_SUCCESS)) {
  398.         sprintf(printBuf,"Bad return code from jmgr\n");
  399.         Log_AtomicEvent("jfetch", printBuf, logPath);
  400.         return T_ROBOTFAILED;
  401.     }
  402.  
  403.     Sock_ReadString(sock, &devNamePtr, 0);
  404.  
  405.     /*
  406.      * ok we have the volume. Quick check to make sure
  407.      * someone else didn't bring the buffer in while we
  408.      * were waiting.
  409.      */
  410.     if ((TBuf_Open(archPath, tBufId, tBufStreamPtr, NULL, O_RDONLY)
  411.          == T_SUCCESS) &&
  412.         (*tBufStreamPtr != -1)) {
  413.         sprintf(printBuf,"Recall aborted. tbuf.%d already here.\n",
  414.             tBufId);
  415.         Log_AtomicEvent("jfetch", printBuf, logPath);
  416.         return T_SUCCESS;
  417.     }
  418.  
  419.     /* Close any old stream */
  420.     if (*inStreamPtr != -1) {
  421.         Dev_CloseVolume(*inStreamPtr);
  422.         *inStreamPtr == -1;
  423.     }
  424.  
  425.     /* Must sleep here, waiting for drive to spin up...*/
  426.     while (((*inStreamPtr=Dev_OpenVolume(devName, O_RDONLY)) == -1) &&
  427.            (retryCnt++ < 10)) {
  428.         sleep(sleepSecs);
  429.     }
  430.     if (*inStreamPtr == -1) {
  431.         sprintf(printBuf,"Couldn't open device %s. errno %d\n",
  432.             devName, syserr);
  433.         Log_AtomicEvent("jfetch", printBuf, logPath);
  434.         return T_IOFAILED;
  435.     } else if (jDebug) {
  436.         fprintf(stderr, "(%d) RecallTBuf: opened vol %d\n",
  437.             Time_Stamp(), volId);
  438.     }
  439.  
  440.     Dev_GetVolStatus(*inStreamPtr, &volStatus);
  441.     if ((volStatus.position != 0) &&
  442.         (Dev_SeekVolume(*inStreamPtr, 0, DEV_ABSOLUTE) != T_SUCCESS)) {
  443.         sprintf(printBuf,"Couldn't rewind device %s. errno %d\n",
  444.             devName, syserr);
  445.         Log_AtomicEvent("jfetch", printBuf, logPath);
  446.         curFilemark = -1;
  447.         return T_IOFAILED;
  448.     }
  449.     curVolId = volId;
  450.     curFilemark = 0;
  451.     }
  452.  
  453.     /* Now reposition if necessary */
  454.     if (curFilemark != filemark)  {
  455.     curFilemark = filemark - curFilemark;
  456.     if (Dev_SeekVolume(*inStreamPtr, curFilemark, DEV_RELATIVE)
  457.      != T_SUCCESS) {
  458.         sprintf(printBuf,"Couldn't seek device %s, %d. errno %d\n",
  459.             devName, curFilemark, syserr);
  460.         Log_AtomicEvent("jfetch", printBuf, logPath);
  461.         curFilemark = -1;
  462.         return T_IOFAILED;
  463.     }
  464.     }
  465.     
  466.     if (jDebug) {
  467.     fprintf(stderr, "(%d) RecallTBuf: seeked vol %d\n",
  468.         Time_Stamp(), volId);
  469.     }
  470.  
  471.     /* open the tbuf stream */
  472.     sprintf(recallPath, "%s/recall.%d\0", archPath, tBufId);
  473.     if ((*tBufStreamPtr=open(recallPath, O_RDWR+O_CREAT, 0600)) < 0) {
  474.     sprintf(printBuf,"Couldn't open recall.%d\n", tBufId);
  475.     Log_AtomicEvent("jfetch", printBuf, logPath);
  476.     Sock_WriteString(sock, parms.userName, 0);
  477.     Sock_WriteInteger(sock, S_CMDFREE);
  478.     Sock_WriteInteger(sock, volId);
  479.     return retCode;
  480.     }
  481.  
  482.     /* Finally, we can read in the buffer */
  483.     size = 0;
  484.     while ((len=Dev_ReadVolume(*inStreamPtr, buf, sizeof(buf))) > 0) {
  485.     if (write(*tBufStreamPtr, buf, len) != len) {
  486.         curFilemark = -1;
  487.         sprintf(printBuf,"Short write to %s. errno %d\n",
  488.             recallPath, syserr);
  489.         Log_AtomicEvent("jfetch", printBuf, logPath);
  490.         return T_IOFAILED;
  491.     }
  492.     size += len;
  493.     /* I thought a filemark would give us EOF but apparently */
  494.     /* not. So we'll interpret a short read as EOF */
  495.     if (len < sizeof(buf)) {
  496.         break;
  497.     }
  498.     }
  499.  
  500.     sprintf(buf, "%s/tbuf.%d\0", archPath, tBufId);    
  501.     if (rename(recallPath, buf) < 0) {
  502.     sprintf(printBuf,"Couldn't rename recall.%d to tbuf.%d. errno %d\n",
  503.         tBufId, tBufId, errno);
  504.     } else {
  505.     sprintf(printBuf,"Restored tbuf.%d\n", tBufId);
  506.     }
  507.     Log_AtomicEvent("jfetch", printBuf, logPath);
  508.     if (jDebug) {
  509.     fprintf(stderr, "(%d) %s",  Time_Stamp(), printBuf);
  510.     }
  511.  
  512.     curFilemark = filemark+1;
  513.  
  514.     return retCode;
  515.  
  516. }
  517.  
  518.  
  519.  
  520. /*
  521.  *----------------------------------------------------------------------
  522.  *
  523.  * GetFileQuery --
  524.  *
  525.  *    Obtain query specification block
  526.  *
  527.  * Results:
  528.  *      return code
  529.  *
  530.  * Side effects:
  531.  *    none.
  532.  *
  533.  *----------------------------------------------------------------------
  534.  */
  535.  
  536. static int
  537. GetFileQuery(sock, fileSpecPtr)
  538.     int sock;                 /* incoming data socket */
  539.     QuerySpec *fileSpecPtr;   /* receiving structure */
  540. {
  541.     int retCode;
  542.     char *abstract;
  543.  
  544.     retCode = Sock_ReadInteger(sock, &fileSpecPtr->firstVer);
  545.     retCode += Sock_ReadInteger(sock, &fileSpecPtr->lastVer);
  546.     retCode += Sock_ReadInteger(sock, (int *)&fileSpecPtr->firstDate);
  547.     retCode += Sock_ReadInteger(sock, (int *)&fileSpecPtr->lastDate);
  548.     retCode += Sock_ReadString(sock, &fileSpecPtr->owner, 1);
  549.     retCode += Sock_ReadString(sock, &fileSpecPtr->group, 1);
  550.     retCode += Sock_ReadInteger(sock, &fileSpecPtr->flags);
  551.     retCode += Sock_ReadInteger(sock, &fileSpecPtr->recurse);
  552.     retCode += Sock_ReadString(sock, &abstract, 1);
  553.  
  554.     sprintf(printBuf,"Query: fv=%d, lv=%d, fd=%s, ld=%s, o=%s, g=%s, flg 0x%x, rec=%d, abs='%s'\n", 
  555.         fileSpecPtr->firstVer, fileSpecPtr->lastVer,
  556.         Time_CvtToString(&fileSpecPtr->firstDate),
  557.         Time_CvtToString(&fileSpecPtr->lastDate),
  558.         fileSpecPtr->owner, fileSpecPtr->group,
  559.         fileSpecPtr->flags, fileSpecPtr->recurse, abstract);
  560.     Log_AtomicEvent("jfetch", printBuf, logPath);
  561.  
  562.     if (*abstract) {
  563.     fileSpecPtr->compAbstract = regcomp(abstract);
  564.     } else {
  565.     fileSpecPtr->compAbstract = NULL;
  566.     }
  567.  
  568.     MEM_FREE("GetFileQuery", abstract);
  569.  
  570.     return retCode;
  571.  
  572. }
  573.  
  574.  
  575.  
  576. /*
  577.  *----------------------------------------------------------------------
  578.  *
  579.  * GetRegExpr --
  580.  *
  581.  *    Read the regular expressions from socket
  582.  *
  583.  * Results:
  584.  *      ptr to array of reg expressions
  585.  *
  586.  * Side effects:
  587.  *    none.
  588.  *
  589.  * Note:
  590.  *      Very inefficient right now. Sorry.
  591.  *
  592.  *----------------------------------------------------------------------
  593.  */
  594.  
  595. static char **
  596. GetRegExpr(sock, countPtr)
  597.     int sock;                 /* incoming socket */
  598.     int *countPtr;            /* number of expressions read */
  599. {
  600.     int i;
  601.     char **ftab = NULL;
  602.     int count;
  603.  
  604.     Sock_ReadInteger(sock, &count);
  605.  
  606.     ftab = (char **)MEM_ALLOC("GetRegExpr",count*sizeof(char *));
  607.     
  608.     for (i=0; i<count; i++) {
  609.     if (Sock_ReadString(sock, ftab+i, 1) == T_IOFAILED) {
  610.         if (ftab) {
  611.         MEM_FREE("GetRegExpr", (char *)ftab);
  612.         }
  613.         *countPtr = 0;
  614.         return NULL;
  615.     }
  616.     Str_StripDots(ftab[i]);
  617.     }
  618.  
  619.     *countPtr = count;
  620.  
  621.     return ftab;
  622. }
  623.  
  624.  
  625.  
  626. /*
  627.  *----------------------------------------------------------------------
  628.  *
  629.  * ReceiveIndxProc --
  630.  *
  631.  *    Accept data produced by indx code
  632.  *
  633.  * Results:
  634.  *      none.
  635.  *
  636.  * Side effects:
  637.  *    Sends info over socket to caller.
  638.  *
  639.  * Note:
  640.  *      This is a callback routine used by MatchVersionsProc in indx.
  641.  *
  642.  *----------------------------------------------------------------------
  643.  */
  644.  
  645. static int
  646. ReceiveIndxProc(statInfoPtr, receiveBlkPtr)
  647.     T_FileStat *statInfoPtr;  /* index information */
  648.     ReceiveBlk *receiveBlkPtr; /* callback info block */
  649. {
  650.     char *archPath = receiveBlkPtr->archPath;
  651.     int sock = receiveBlkPtr->sock;
  652.     ArchConfig *archConfigPtr = receiveBlkPtr->archConfigPtr;
  653.     static int curTBufId = -1;
  654.     static int tBufStream;
  655.     int retCode;
  656.     static int inStream = -1;
  657.  
  658.     Admin_CvtTBufId(archPath, statInfoPtr->tBufId,
  659.             &statInfoPtr->volId, &statInfoPtr->filemark);
  660.     if (parms.flags & T_NODATA) {
  661.     if (jDebug) {
  662.         fprintf(stderr,"ReceiveIndxProc: sending %s\n",
  663.             statInfoPtr->fileName);
  664.     }
  665.     retCode = Sock_WriteFileStat(sock, statInfoPtr, 0);
  666.     } else {
  667.     if (curTBufId != statInfoPtr->tBufId) {
  668.         if (curTBufId != -1) {
  669.         TBuf_Close(tBufStream, -1, -1);
  670.         }
  671.         if ((retCode=RecallTBuf(archPath, &tBufStream, statInfoPtr,
  672.                archConfigPtr, &inStream)) != T_SUCCESS) {
  673.         return retCode;
  674.         }
  675.         curTBufId = statInfoPtr->tBufId;
  676.         Admin_UpdateLRU(parms.root, parms.arch, curTBufId, curTBufId);
  677.     }
  678.     retCode = ReturnFileData(sock, statInfoPtr, tBufStream);
  679.     }
  680.     
  681.     return retCode;
  682. }
  683.  
  684.     
  685.  
  686. /*
  687.  *----------------------------------------------------------------------
  688.  *
  689.  * ReturnFileData --
  690.  *
  691.  *    Pump file data back to user
  692.  *
  693.  * Results:
  694.  *      none.
  695.  *
  696.  * Side effects:
  697.  *    Sends info over socket to caller.
  698.  *
  699.  *----------------------------------------------------------------------
  700.  */
  701.  
  702. static int
  703. ReturnFileData(sock, statInfoPtr, tBufStream)
  704.     int sock;                 /* outgoing socket */
  705.     T_FileStat *statInfoPtr;  /* file meta info */
  706.     int tBufStream;           /* source buffer */
  707. {
  708.     int size;
  709.     int count;
  710.     char buf[T_BUFSIZE];
  711.     int retCode;
  712.  
  713.     if ((retCode=TBuf_FindFile(tBufStream, statInfoPtr)) != T_SUCCESS) {
  714.     if (jDebug) {
  715.         fprintf(stderr,"Failed to find file %s\n",
  716.             statInfoPtr->fileName);
  717.     }
  718.     return retCode;
  719.     }
  720.     size = statInfoPtr->size;
  721.     retCode = Sock_WriteFileStat(sock, statInfoPtr, 0);
  722.  
  723.     while ((retCode == T_SUCCESS) && (size > 0)) {
  724.     count = (size > sizeof(buf)) ? sizeof(buf) : size;
  725.     if ((count=read(tBufStream, buf, count)) < 0) {
  726.         syserr = errno;
  727.         retCode = T_BUFFAILED;
  728.         break;
  729.     }
  730.     if (Sock_WriteNBytes(sock, buf, count) != count) {
  731.         retCode = T_IOFAILED;
  732.         break;
  733.     }
  734.     size -= count;
  735.     }
  736.  
  737.     return retCode;
  738. }
  739.  
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * VerifyClient --
  745.  *
  746.  *    Check authorization of client for this archive
  747.  *
  748.  * Results:
  749.  *    return Code
  750.  *
  751.  * Side effects:
  752.  *    Sends negative ack if not authorized else send go-ahead msg.
  753.  *      Builds Caller structure for future use.
  754.  *
  755.  *----------------------------------------------------------------------
  756.  */
  757.  
  758. static int
  759. VerifyClient(archPath, sock, callerPtr)
  760.     char *archPath;           /* archive pathname */
  761.     int sock;                 /* caller socket */
  762.     Caller *callerPtr;        /* caller id */
  763. {
  764.     int retCode;
  765.     char perm;
  766.  
  767.     callerPtr->userName = Str_Dup(parms.userName);
  768.     callerPtr->hostName = Str_Dup(parms.hostName);
  769.     callerPtr->groupName = Str_Dup(parms.groupName);
  770.  
  771.     if ((retCode=Admin_CheckAuth(archPath, callerPtr, &perm)) != T_SUCCESS) {
  772.     sprintf(printBuf,"Admin_CheckAuth failed: errno %d\n", syserr);
  773.     Log_AtomicEvent("jfetch", printBuf, logPath);
  774.     Sock_SendRespHdr(sock, retCode, syserr);
  775.     return T_NOACCESS;
  776.     }
  777.  
  778.     if ((perm != 'R') && (perm != 'W') && (perm != 'O')) {
  779.     sprintf(printBuf,"Access denied: %s %s from %s\n",
  780.         parms.userName, parms.groupName, parms.hostName);
  781.     Log_AtomicEvent("jfetch", printBuf, logPath);
  782.     Sock_SendRespHdr(sock, T_NOACCESS, 0);
  783.     return T_NOACCESS;
  784.     }
  785.  
  786.     /*
  787.      * if user is owner, change his name to '*' so Str_Match succeeds.
  788.      */
  789.     if (perm == 'O') {
  790.     *(callerPtr->userName) = '*';
  791.     *(callerPtr->userName+1) = '\0';
  792.     }
  793.  
  794.     return T_SUCCESS;
  795. }
  796.